#include "PsnrCompare.h"

#include <chrono>

double PsnrCompare::matCompare(std::string matSrcPath, std::string matDstPath)
{
    cv::Mat matSrc = cv::imread(matSrcPath);
    cv::Mat matDst = cv::imread(matDstPath);

    if (matSrc.empty() || matDst.empty())
    {
        return 0.0;
    }

    cv::resize(matDst, matDst, cv::Size(matSrc.cols, matSrc.rows));

    auto start = std::chrono::steady_clock::now();

    double result = this->getPSNR(matSrc, matDst);

    auto end = std::chrono::steady_clock::now();

    std::cout << "Time of PSNR CPU " << std::chrono::duration<double, std::micro>(end - start).count() << " milliseconds."
        << " With result of: " << result << std::endl;

    return result;
}

double PsnrCompare::getPSNR(const cv::Mat& matSrc, const cv::Mat& matDst)
{
    cv::Mat s1;
    cv::absdiff(matSrc, matDst, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2

    cv::Scalar s = cv::sum(s1);         // sum elements per channel

    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

    if (sse <= 1e-10) // for small values return zero
        return 0.0;


    double  mse = sse / (double)(matSrc.channels() * matSrc.total());
    double psnr = 10.0 * log10((255 * 255) / mse);
    return psnr;
}
